﻿using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace CoreEx.Common.Repository
{
    /// <summary>
    /// Represents a class that is capable of tracking the state 
    /// of an object that implements the <see cref="INotifyPropertyChanged"/> interface.
    /// </summary>
    public interface IStateTracker
    {
        /// <summary>
        /// Fires when a trackable object is registered in the state tracker
        /// </summary>
        event EventHandler<ObjectRegisteredEventArgs> ObjectRegistered;
        
        /// <summary>
        /// Starts tracking the <paramref name="target"/> instance.
        /// </summary>
        /// <remarks>
        /// The <paramref name="target"/> instance must implement <see cref="INotifyPropertyChanged"/> in order to be trackable.
        /// </remarks>
        /// <param name="target">The trackable target instance.</param>
        void Register(object target);
        
        /// <summary>
        /// Starts tracking the <paramref name="target"/> instance.
        /// </summary>
        /// <remarks>
        /// The <paramref name="target"/> instance must implement <see cref="INotifyPropertyChanged"/> in order to be trackable.
        /// </remarks>
        /// <param name="target">The trackable target instance.</param>
        /// <param name="initialState">The initial state for the <paramref name="target"/> instance.</param>
        void Register(object target, StateType initialState);
        
        /// <summary>
        /// Gets the <see cref="IObjectState"/> for a target instance.
        /// </summary>
        /// <param name="target">The target instance for which to return the <see cref="IObjectState"/></param>
        /// <returns><see cref="IObjectState"/></returns>
        IObjectState GetState(object target);

        /// <summary>
        /// Gets a <see cref="bool"/> value that indicates if the <paramref name="target"/> 
        /// instance is tracked by this <see cref="IStateTracker"/>
        /// </summary>
        /// <param name="target">The object to locate in this <see cref="IStateTracker"/></param>
        /// <returns><b>true</b> if the <paramref name="target"/> instance is tracked by this <see cref="IStateTracker"/>, otherwise <b>false</b></returns>
        bool Contains(object target);

        /// <summary>
        /// Gets all changes monitored by this <see cref="IStateTracker"/>
        /// </summary>
        /// <returns>An <see cref="IEnumerable{T}"/> containing <see cref="IObjectState"/> instances that represents all currently dirty objects.</returns>
        IEnumerable<IObjectState> GetChanges();

        /// <summary>
        /// Resets the <see cref="IStateTracker"/> by setting the state of tracked objects to <see cref="StateType.NotModified"/>.
        /// </summary>        
        void AcceptChanges();

    }
}
